const { defineConfig } = require("@vue/cli-service");
const fs = require("fs");
const path = require("path");
// const webpack = require("webpack"); // 引入webpack库

const resolve = dir => path.join(__dirname, dir);

const { NODE_ENV, VUE_APP_PUBLIC_PATH, VUE_APP_API } = process.env;
const IS_PROD = ["production", "prod"].includes(NODE_ENV); // 判断是否发布模式

const pages = (function () {
  const pages = fs.readdirSync("./src/pages");
  const pagesObj = {};
  pages.forEach(item => {
    let config = {};
    if (fs.existsSync(`./src/pages/${item}/config.json`)) {
      config = require(`./src/pages/${item}/config.json`);
      // const config = JSON.parse(fs.readFileSync(`./src/pages/${item}/config.json`, "utf-8"));
    }

    const entry = config.entry || `src/pages/${item}/main.ts`;
    if (fs.existsSync("./" + entry)) {
      const title = config.title || item;
      const template = config.template || "public/index.html";

      pagesObj[item] = {
        template,
        // filename: "[name].cshtml",
        entry,
        title,
        chunks: config.chunks || ["chunk-vendors", "chunk-vue", "chunk-common", "runtime", item],
        version: getCurrentVersion(),
      };
    }
  });
  return pagesObj;
})();

function getCurrentVersion() {
  let pkg = fs.readFileSync(resolve("./package.json"));
  pkg = JSON.parse(pkg);
  return pkg.version;
}

module.exports = defineConfig({
  publicPath: IS_PROD ? VUE_APP_PUBLIC_PATH : "./", // 默认'/'，部署应用包时的基本 URL
  integrity: false,
  productionSourceMap: !IS_PROD, // 生产环境的 source map
  pages,
  transpileDependencies: true,
  configureWebpack: {
    resolve: {
      alias: {
        "@assets": path.join(__dirname, "src/assets"),
        "@framework": path.join(__dirname, "src/framework"),
      },
    },
    externals: {
      vue: "Vue",
      // "element-ui": "ELEMENT", //! 为了解决自定义弹窗组件的zIndex 问题，element-ui 不通过CDN方式进行加载
      lodash: "_",
    },
  },
  devServer: {
    client: {
      overlay: {
        errors: false, // 错误时显示
        warnings: false, // 警告不显示
      }, // 取消遮罩错误的显示
      progress: true, // 在浏览器中以百分比显示编译进度
      reconnect: true, // 告诉 dev-server 它应该尝试重新连接客户端的次数。当为 true 时，它将无限次尝试重新连接。
    },
    proxy: {
      "/proxy": {
        target: VUE_APP_API,
        pathRewrite: {
          "^/proxy": "",
        },
        changeOrigin: true, // 开启代理，在本地创建一个虚拟服务端
        // secure: true,
        // ws:true  //开始websocket 代理
      },
    },
    // https: true,
  },
  chainWebpack: config => {
    // 按需加载时候， css 格式文件不带扩展名时无法直接进行加载的问题，babel-plugin-import 导入element 的样式时没有带扩展名出现的问题
    config.resolve.extensions.add(".css").end();
    // 修复HMR
    // config.resolve.symlinks(true);

    config.plugin("define").tap(args => {
      const newVersion = getCurrentVersion();
      // 定义process.env.VERSION ，用于访问当前版本
      args[0]["process.env"].VERSION = JSON.stringify(newVersion);
      return args;
    });
    Object.keys(pages).forEach(item => {
      config.plugins.delete(`prefetch-${item}`); // 移除 prefetch 插件
      config.plugins.delete(`preload-${item}`); // 移除 preload 插件
    });

    // 设置 svg-sprite-loader
    // config.module.rule("svg").exclude.add(resolve("src/icons/svg")).end();
    // config.module
    //   .rule("icons")
    //   .test(/\.svg$/)
    //   .include.add(resolve("src/icons/svg"))
    //   .end()
    //   .use("svg-sprite-loader")
    //   .loader("svg-sprite-loader")
    //   .options({
    //     symbolId: "svg-[name]",
    //   })
    //   .end();

    // 设置保留空格
    config.module
      .rule("vue")
      .use("vue-loader")
      .loader("vue-loader")
      .tap(options => {
        options.compilerOptions.preserveWhitespace = true;
        return options;
      })
      .end();

    //! 影响调试过程中实际执行代码文件的映射，暂时去除。
    // https://webpack.js.org/configuration/devtool/#development
    // config.when(IS_PROD, config => config.devtool("cheap-source-map"));

    config.when(IS_PROD, config => {
      // 忽略 moment下 除 zh-cn 所有语言包的压缩，
      // config.plugin("ignore").use(new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn$/));
      // 压缩代码
      config.optimization.minimize(true);

      const pageChunks = Object.fromEntries(
        Object.keys(pages).map(m => [
          m,
          {
            name: `page-${m}-chunk-vendors`,
            test: resolve(`src/pages/${m}`),
            priority: 5,
            minChunks: 1,
            chunks: "initial", // 只从入口模块进行拆分
            // chunks: "all",
          },
        ])
      );

      // 分割模块配置
      config.optimization.splitChunks({
        // filename: "[name].bundle.js",
        // chunks: "all",
        //!  默认为 async,只会把异步加载的模块抽离出来
        //!  all，会将异步模块和同步模块全部抽来出来
        //!  initial， 只从入口模块进行拆分，能够处理同步和异步模块，所以会存在同个模块多次打包的可能

        cacheGroups: {
          // lang_zhCN: {
          //   name: "chunk-zh-CN",
          //   priority: 10,
          //   test: resolve("src/lang/zh-CN.ts"),
          //   chunks: "all", // 不管是同步的还是异步的模块都打包到一个里面
          // },

          ...pageChunks,

          components: {
            name: "chunk-components",
            test: resolve("src/components"),
            priority: 1,
            chunks: "all", // 不管是同步的还是异步的模块都打包到一个里面
          },
          framework: {
            name: "chunk-framework",
            test: resolve("src/framework"),
            priority: 1,
            chunks: "all", // 不管是同步的还是异步的模块都打包到一个里面
          },

          // 从node_modules 中分离的文件
          "pinyin-pro": {
            name: "chunk-pinyin-pro",
            test: /[\\/]node_modules[\\/](.*)@pinyin-pro[\\/](.*)/,
            chunks: "all", // 异步模块和同步模块都合并进来
            priority: -5,
          },
          "vxe-table": {
            name: "chunk-vxe-table",
            test: /[\\/]node_modules[\\/](.*)@vxe-table[\\/](.*)/,
            chunks: "all", // 异步模块和同步模块都合并进来
            priority: -5,
          },
          "xe-utils": {
            name: "chunk-xe-utils",
            test: /[\\/]node_modules[\\/](.*)@xe-utils[\\/](.*)/,
            chunks: "all", // 异步模块和同步模块都合并进来
            priority: -5,
          },
          "element-ui": {
            name: "chunk-element-ui",
            test: /[\\/]node_modules[\\/](.*)@element-ui[\\/](.*)/,
            chunks: "all", // 异步模块和同步模块都合并进来
            priority: -5,
          },

          echarts: {
            name: "chunk-echarts",
            test: /[\\/]node_modules[\\/](.*)@echarts[\\/](.*)/,
            chunks: "all", // 异步模块和同步模块都合并进来
            priority: -5,
          },

          oidcClient: {
            name: "chunk-oidc-client",
            test: /[\\/]node_modules[\\/](.*)@oidc-client[\\/](.*)/,
            chunks: "all", // 异步模块和同步模块都合并进来
            priority: -5,
          },

          vue: {
            name: "chunk-vue",
            test: /[\\/]node_modules[\\/](.*)@vue[\\/](.*)/,
            chunks: "all", // 异步模块和同步模块都合并进来
            priority: -5,
          },

          defaultVendors: {
            name: "chunk-vendors",
            // automaticNamePrefix: "vendors",
            test: /[\\/]node_modules[\\/]/,
            priority: -10,
            chunks: "initial", // 只从入口模块进行拆分
            enforce: true, // 无视这些规则来进行打包；打包的时候出现公共模块未进行打包，导致入口文件过大，重复依赖第三方模块 minSize, minChunks, maxAsyncRequests and maxInitialRequests
            // reuseExistingChunk: true,
          },

          // 其余公共组件的处理
          common: {
            name: "chunk-common",
            minChunks: 2,
            priority: -20,
            // chunks: "initial",
            reuseExistingChunk: true,
          },
        },
      });
      // 配置为单页面应用程序分割代码配置
      config.optimization.runtimeChunk("single");
    });
  },
  css: {
    extract: IS_PROD,
    sourceMap: !IS_PROD,
    // requireModuleExtension: true,
    loaderOptions: {
      css: {
        //! 注意：以下配置在 Vue CLI v4 与 v3 之间存在差异。
        //! Vue CLI v3 用户可参考 css-loader v1 文档
        //! https://github.com/webpack-contrib/css-loader/tree/v6.7.1
        modules: {
          auto: true,
          // mode: "global", // local | "global" | "pure" | "icss"
          localIdentName: "[local]--[hash:base64:8]",
          exportLocalsConvention: "camelCaseOnly", // css 以模块导入时，会将svg-icon 的格式转换为 svgIcon 的写法进行使用
          // namedExport: true,
          // exportOnlyLocals: true,
        },
      },
      scss: {
        // 向全局sass样式传入共享的全局变量, $src 可以配置图片cdn前缀
        // 详情: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
        additionalData: `
          `,
      },
    },
  },
});
